package com.spring.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

/**
 * @Description:切面类
 * @Aspect:切面类注解,在切面类中定义切入点和通知
 * @EnableAspectJAutoProxy:开启SpringAOP的自动代理模式
 */

@Component

@Aspect
//在切面类中定义 切入点和通知

@EnableAspectJAutoProxy
//@EnableAspectJAutoProxy:开启SpringAOP的自动代理模式

public class MyAspect {
    /**
     * 定义切入点
     * myPointcut():切入点的名称，可以通过该名称来引入切入点
     *
     * @Pointcut("execution()"):切入点表达式，SpringAOP中使用切入点表达式定义连接点(定义要拦截的方法) execution(切入点表达式), 切入点表达式, 格式:方法返回类型 类的完整路径.方法名(参数列表)
     * 指定某个具体方法:void com.jiazhong.service.impl.UserServiceImpl.add()
     * 使用通配符指定方法:* com.jiazhong.service.impl..*.*(..)
     * 指定某个些类中的所有方法，但排序某些方法(拦截类中的大多数方法，但某个方法不拦截):execution(* com.jiazhong.service.impl..*.*(..)) && !execution(* com.jiazhong.service.impl..*.getUsers(..))
     */

    //  * :表示任意返回值     del(..)中的  .. 表示任意参数列表
   // @Pointcut("execution(* com.spring.service.impl..*(..))")
    @Pointcut("execution(void com.spring.service.impl.UserServiceImpl.del())")
    private void myPointCut() {

    }

    /***
     * 定义通知
     * 前置通知-在目标方法调用前执行
     * @Before:前置通知注解
     * myPointcut():切入点
     */
//    @Before("myPointCut()")
//    public void beforeAdvice() {
//        System.out.println("前置通知");
//    }
//
//    //后置通知-在目标方法调用后执行(不出现异常的情况下)
//    @AfterReturning("myPointCut()")
//    public void afterAdvice() {
//        System.out.println("后置通知");
//    }
//
//
//    //异常通知-在方法执行时出现异常才执行
//    @AfterThrowing("myPointCut()")
//    public void afterThrowing() {
//        System.out.println("异常通知");
//    }
//
//
//    //* 最终通知-无论方法是否出现异常都会被执行...
//    @After("myPointCut()")
//    public void finallyAdvice() {
//        System.out.println("最终");
//    }


    /**
     * 环绕通知
     // @param proceedingJoinPoint  连接点处理器对象(该对象中包含目标方法)
     */

    @Around("myPointCut()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) {
        try{
            System.out.println("前置通知");
            //发起对目标方法的调用
            Object result = proceedingJoinPoint.proceed();
            Signature signature = proceedingJoinPoint.getSignature();
            String name = signature.getName();
            System.out.println(name);
            System.out.println("后置通知");
        }catch (Exception e){
            System.out.println("异常通知");
            //异常通知只针对方法的异常。其他部分出现异常不会进入异常通知
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        } finally {
            System.out.println("最终通知");
        }
    }

}
